Technical Note TN2044
Decompressing DV frames and accessing the pixels

目次

このテクニカルノートでは、伸張シーケンスを使って、RGB オフスクリーン領域に DV フレームを伸張し、フレームの各ピクセルに直接アクセスする方法を説明します。

このテクニカルノートにおける手順は、 画像記述で表された、QuickTime がサポートする任意の圧縮画像形式に適用できます。圧縮された画像データは、QuickTime Movie、Sequence Grabber またはアプリケーションが提供するバッファから引き出せます。

更新:[2002 年 4 月 11 日]






はじめに

単一の DV フレームを、バッファから RGB オフスクリーン領域に伸張した後、ピクセルに直接アクセスする全体の手順は簡単です。定期伸張を考慮しない場合はなおさらです。ただし、その方法は 2 通りあります。たとえば、各フレームを 1 つの画像として扱い、DecompressImage または FDecompressImage を使って、この「単一のフレーム」をピクセルマップに伸張することができます。これは、単一の画像に対して行うにはいい方法ですが、ImageDescription 構造体で表された共通の画像記述を使う、連続する同じ形式の画像を伸張する最速の方法ではありません。

より効率的な方法は、伸張シーケンスを使うことです。

Image Compression Manager (ICM)が提供する API セットを使用すれば、共通の画像記述を使う画像のシーケンスを伸張できます。シーケンスの各画像はフレームと呼ばれます。伸張シーケンスは、DecompressSequenceBeginS を呼び出すことによって開始し、シーケンスの各フレームは DecompressSequenceFrameWhen を呼び出すことによって処理されます。完了すると、CDSequenceEnd が呼び出され、シーケンスが終了します。CDSequenceBusy を呼び出せば、現在の処理の状況を確認できます。伸張シーケンスを制御するパラメータを操作できる DSequence Parameter API もいくつかあります。たとえば、ソースレクタングル、変換行列、精度などを操作できます。

開始

画像を伸張する場所を決め、ソースデータを記述する画像記述を作成し、伸張対象の画像の量を決めた後、処理のマッピング行列を作成します。これらのパラメータは、伸張リクエストを行うときに、DecompressSequenceBeginS の呼び出しに指定しなければなりません。

伸張先は、グラフィックスポートとして指定し、画像ソースのサイズはソース画像の座標系におけるレクタングルで表します。ソース画像全体を示すときには、NULL を使用できます。様々なサイズの伸張先に合わせた拡大縮小などの変換をサポートする場合は、画像を伸張先のグラフィックスポートにマッピングする方法を表す行列を指定します。

重要:
クロッピングされ、拡大縮小されていない DV をより小さい伸張先(1/4 サイズなど)に描画するために、コードがより小さいソースレクタングル(1/4 サイズなど)を渡すと、QuickTime 5 の DV 固有のバグにより、この伸張リクエストが誤って解釈され、このレクタングルに合うようにフレームが拡大縮小されてしまいます。このリクエストの正しい解釈は、通常のサイズにクロッピングされた DV フレームの左上隅を描画することです。

このバグは QuickTime 6 で修正される予定です。このバグが原因で、お使いのコードが上記のように動作した場合は、コードを必ず修正し、DecompressSequenceBeginS の呼び出しの中で行列を使用し、フレームがオフスクリーンの GWorld に合わせて拡大縮小されるようにしてください。このアプローチは、すべてのバージョンの QuickTime で正しく動作します。


画像に関連付けられた画像記述構造体を調べることで、ソース画像のサイズが分かります。また、その画像データを熟知している場合は、画像記述を自分で作成することもできます。画像記述構造体には、圧縮された画像またはシーケンスの特性を定義している情報が含まれます。1 つの画像記述構造体は、1 つまたは複数の圧縮されたフレームに関連付けられている場合があります。図 1 を参照してください。

画像記述拡張も含め、画像記述構造体における解凍された Y´CbCr ビデオの表現の詳細については、流氷通信 #19 を参照してください。

ImageDescription

圧縮データの画像記述を作成します。リスト 1 を参照してください。

struct ImageDescription {
    long idSize; // 追加的なデータ(シーケンスデータごとの CLUT やその他の
                 // データ)を含む ImageDescription の合計サイズ
    CodecType cType;           // このデータを圧縮したコーデックの種類
    long      resvd1;          // Apple での使用のため、予約されている
    short     resvd2;          // Apple での使用のため、予約されている
    short     dataRefIndex;    // ゼロに設定
    short     version;         // このデータのバージョン
    short     revisionLevel;   // このデータを圧縮したコーデックのバージョン
    long      vendor;          // このデータを圧縮したコーデックのメーカー
    CodecQ    temporalQuality; // 一時的な品質因子
    CodecQ    spatialQuality;  // 空間的な品質因子
    short     width;           // このデータの横のピクセル数
    short     height;          // このデータの縦のピクセル数
    Fixed     hRes;            // 水平解像度
    Fixed     vRes;            // 垂直解像度
    long      dataSize;        // 分かる場合は、この画像記述子の
                               // データサイズ
    short     frameCount;      // この記述を適用するフレーム数
    Str31     name;            // コーデック名(インストールされていない場合)
    short     depth;           // このデータの深さ(1 〜 32)または
                               // (33 〜 40 グレイスケール)
    short     clutID;          // CLUT ID か、0 ならば CLUT が後に続き
                               // CLUT がない場合は -1 を指定
};

図 1 画像記述構造体


// 圧縮されたデータを表す画像記述を作成する。
// 戻されるハンドルを破棄するのは作成者の責任。
// 画像記述の値を変更し、PAL (kDVCPALCodecType) など、
// 他の任意の圧縮データ形式に対応できるようにする。
ImageDescriptionHandle MakeImageDescriptionForNTSCDV(void)
{
    ImageDescriptionHandle hImageDescription = NULL;

    hImageDescription =
        (ImageDescriptionHandle)
        NewHandleClear(sizeof(ImageDescription));

    if (NULL != hImageDescription) {
        (**hImageDescription).idSize = sizeof(ImageDescription);
        (**hImageDescription).cType = kDVCNTSCCodecType;

                // DV に temporalQuality がない
        (**hImageDescription).temporalQuality = 0;
        (**hImageDescription).spatialQuality = codecNormalQuality;
        (**hImageDescription).width = 720;
        (**hImageDescription).height = 480;
        (**hImageDescription).hRes = 72 << 16;
        (**hImageDescription).vRes = 72 << 16;
        (**hImageDescription).frameCount = 1;
        (**hImageDescription).depth = 24;
        (**hImageDescription).clutID = -1;
    }

    return hImageDescription;
}

リスト 1 圧縮データを説明する画像記述の作成

オフスクリーン

QTNewGWorld を使って、伸張先のオフスクリーン領域を作成します。図 2 を参照してください。DV コーデックの場合、24 ビット RGB 形式(k24RGBPixelFormat)は最良の伸張先ではなく、32 ビット RGB 形式(k32ARGBPixelFormat)の方がより効率的な(より速い)伸張先である点に注意してください。

32 ビット RGB 形式のオフスクリーンを作成します。リスト 2 を参照してください。

OSErr QTNewGWorld(
    GWorldPtr   *offscreenGWorld, // GWorld へのポインタが戻される
    OSType      PixelFormat;      // 新しい GWorld のピクセル形式
    const Rect  *boundsRect,      // 境界およびポートレクタングル
    CTabHandle  cTable,           // ColorTable。デフォルトは NULL 
    GDHandle    aGDevice,         // GDevice。NULL に設定
    GWorldFlags flags);           // フラグ。デフォルトは 0

図 2 QTNewGWorld API


// 出力先として 32 ビット GWorld を作成する(DV の場合は 720 x 480)。
// この関数はピクセルマップをロックする。
OSErr MakeGWorld(short inWidth, short inHeight,
                            GWorldPtr *outDestGWorld)
{
    Rect  theBounds = {0, 0};

    OSErr err = noErr;

    theBounds.right  = inWidth;
    theBounds.bottom = inHeight;
    *outDestGWorld = NULL;

    err = QTNewGWorld(outDestGWorld,     // オフスクリーンへの
                                         // ポインタが戻される
                     k32ARGBPixelFormat, // 新しい GWorld のピクセル形式
                     &theBounds,       // オフスクリーン PixMap の境界
                                         // およびポートレクタングル
                     NULL,               // ColorTable のハンドル
                     NULL,               // GDevice のハンドル
                     0);                 // フラグ

    if (noErr == err)
        // LockPixels を呼び出し、ピクセルマップからのコピー中
        // または描画中に、オフスクリーンのピクセル画像の
        // ベースアドレスが移動しないようにする。
        LockPixels(GetGWorldPixMap(*outDestGWorld));

    return err;
}

リスト 2 伸張先として 32 ビット GWorld を作成

シーケンスのセットアップ

ICM の DecompressSequenceBeginS 関数を呼び出し、画像シーケンスの伸張に必要なセットアップを行います。図 3 を参照してください。DecompressSequenceBegin も使用できますが、ここでは DecompressSequenceBeginS を代わりに使用しています。

DecompressSequenceBeginS の呼び出しは、シーケンスを開始するために使われ、シーケンスの伸張処理を制御する多くのパラメータを指定します。ICM は、この処理に必要なシステムリソースを割り当て、シーケンスを一意に特定する ImageSequence ID (seqID)を戻します。

伸張シーケンスを開始します。リスト 3 を参照してください。

OSErr DecompressSequenceBeginS(
    ImageSequence          *seqID,   // 一意の seqID を戻す
    ImageDescriptionHandle desc,     // 圧縮されたデータの記述
    Ptr                    data,     // 前処理に使う
                                     // 圧縮データへのポインタ
    long                   dataSize, // データバッファのサイズ
    CGrafPtr               port,     // 伸張先ポート
    GDHandle               gdh,      // 伸張先の GDevice
    const Rect             *srcRect, // 画像の伸張対象範囲
    MatrixRecordPtr        matrix,   // 伸張時に適用する変換
    short                  mode,     // 処理のグラフィックス転送モード
    RgnHandle              mask,     // 伸張時に適用されるマスク
    CodecFlags             flags,    // 中間バッファの割り当てフラグ
    CodecQ                 accuracy  // 処理に求められる精度
    DecompressorComponent  codec);   // 使用するデコンプレッサ
                                     // 特殊な識別子の場合もある

図 3 DecompressionSequenceBeginS API


// 一連のフレームの伸張処理を開始することを通知する。
// CodecQ パラメータに codecHighQuality を使うと、デコンプレッサに、
// 妥当なパフォーマンスで達成できる最高の画像品質でレンダリング
// するように指示できる。速度を優先するときは、CodeQ の設定値を
// 小さくするとよい場合もある。 
OSErr MakeDecompressionSequence(
    ImageDescriptionHandle inImageDescription,
    GWorldPtr inDestGWorld, ImageSequence *outSeqID)
{
    Rect         theSrcBounds = {0, 0};
    Rect         theDestBounds;
    MatrixRecord rMatrix;

    *outSeqID = 0;

    if (NULL == inImageDescription) return paramErr;

    // *** DV ソースに関する注意事項 ***
    // クロッピングされ、拡大縮小されていない DV をより小さい伸張先
    // (1/4 サイズなど)に描画するために、コードがより小さいソース
    // レクタングル(1/4 サイズなど)を渡すと、QuickTime 5 の DV 固有
    // のバグにより、この伸張リクエストが誤って解釈され、このレクタングルに
    // 合うようにフレームが拡大縮小されてしまう。このリクエストの
    // 正しい解釈は、通常のサイズにクロッピングされた DV フレームの
    // 左上隅を描画する。このバグは QuickTime 6 で修正される予定。
    // このバグが原因で、お使いのコードが上記のように動作した場合は、
    // コードを必ず修正し、DecompressSequenceBeginS の呼び出しの中で
    // 行列を使用し、フレームがオフスクリーンの GWorld に対して拡大縮小
    // されるようにすること。このアプローチは、すべてのバージョンの 
    // QuickTime で正しく動作する。
    // *************************************

    // ソースの境界から伸張先の境界に合わせて拡大縮小するための変換行列を
    // 作成する。DecompressSequenceBeginS の呼び出しのソースレクタングルに
    // NULL を使うと、ソース画像全体を伸張するように指定できる。
    GetPortBounds(inDestGWorld, &theDestBounds);
    theSrcBounds.right  = (*inImageDescription)->width;
    theSrcBounds.bottom = (*inImageDescription)->height;

    RectMatrix(&rMatrix, &theSrcBounds, &theDestBounds);

    return DecompressSequenceBeginS(
                outSeqID,           // シーケンスの一意の ID を受け取る
                                    // フィールドへのポインタ
                inImageDescription, // 画像記述の構造体に対する
                                    // ハンドル
                NULL,               // 圧縮された画像データへの
                                    // ポインタ(前処理に使用)
                0,                  // 画像データのサイズ
                inDestGWorld,       // 伸張先の画像のポート
                NULL,               // グラフィックスデバイスのハンドル。
                                    // ポートが設定されている場合は、
                                    // NULL に設定
                NULL,               // 画像の伸張対象の範囲
                                    // 定義するソースレクタングル。
                                    // 画像全体を指定する場合は NULL
                &rMatrix,           // 変換行列
                srcCopy,            // 転送モードの指定子
                (RgnHandle)NULL,    // マスクとして使用するクリッピング
                                    // リージョンを出力先の座標系で表す
                0,                  // フラグ
                codecHighQuality,   // 伸張における精度
                anyCodec);          // コンプレッサの識別子、または
                                    // bestSpeedCodec などの特殊な識別子
}

リスト 3 フレームのシーケンスの伸張処理の開始を通知する

GWorldPtr から返された QTNewGWorld を、伸張先のポートのパラメータとして使います。CodecQ パラメータに codecHighQuality を使うと、デコンプレッサに、妥当なパフォーマンスで達成できる最高の画像品質でレンダリングするように指示できます。速度を優先するときは、CodecQ の設定値を小さくするとよい場合もあります。

フレームの伸張

シーケンスが開始されると、DecompressSequenceFrameS または DecompressSequenceFrameWhen を呼び出すことによって、シーケンスの各フレームは伸張のための待ち行列に入ります。図 4 を参照してください。DecompressSequenceBeginS から返された一意の ImageSequence ID を、最初のパラメータとして渡します。

OSErr DecompressSequenceFrameWhen(
    ImageSequence              seqID,               // 一意の segID
    Ptr                        data,                // 圧縮データへの
                                                    // ポインタ
    long                       dataSize,            // データバッファのサイズ
    CodecFlags                 inFlags,             // 制御フラグ
    CodecFlags                 *outFlags,           // ステータスフラグ
    ICMCompletionProcRecordPtr asyncCompletionProc, // 非同期完了
                                                    // プロシージャレコード
    const ICMFrameTimeRecord   *frameTime);         // フレームの時間情報

図 4 DecompressSequenceFrameWhen API

ICM は、伸張処理を管理し、適切なコーデックコンポーネントを呼び出して作業を行います。その結果、DecompressSequenceBeginS の呼び出しで指定された場所にフレームが伸張されます。

フレームを伸張します。リスト 4 を参照してください。

// DecompressSequenceFrameWhen を包むシンプルな
// ラッパー。完了処理と frameTime を指定しない。
// イン/アウトフラグをし、
// 伸張処理は即座に実行される。
OSErr DecompressFrameNow(ImageSequence inSequenceID,
                        Ptr inBuffer, long inBufferSize)
{
    return DecompressSequenceFrameWhen(inSequenceID,
            inBuffer, inBufferSize, 0, NULL, NULL, NULL);
}

リスト 4a DecompressSequenceFrameWhen を包むシンプルなラッパー


// 次のような構造体を使えば、フレームごとに情報を
// トラッキングできる。
typedef struct {
    ImageSequence              seqID;      // 伸張シーケンス ID
    Ptr                        pSrcBuffer; // 圧縮データへのポインタ
    long                       bufSize;    // 圧縮画像データのサイズ
    ICMCompletionProcRecordPtr
                    pCompletionProc;       // ICMCompletionProcRecord への
                                           // ポインタ
    Boolean                    isDestDone; // ICM が出力先を使い終ったかどうか
    OSErr                      rc;         // リターンコード
} FrameRecord, *FrameRecordPtr, **FrameRecordHdl;

// DecompressSequenceFrameWhen を包む別の方法。
// FrameRecordPtr は、アプリケーションに関連付けられている
// フレームごとに情報をトラッキングする何らかの型のデータ構造体
// とする。
OSErr DecompressFrame(FrameRecordPtr inFrame)
{
    if (inFrame->pCompletionProc) {
        // 完了処理を用意する場合は、呼び出しがあった
        // 場合に引き出されるようにフレームを格納しておく
        inFrame->pCompletionProc->completionRefCon = (long)inFrame;
    }

    return DecompressSequenceFrameWhen(inFrame->seqID,
                inFrame->pSrcBuffer, inFrame->bufSize,
                0, NULL, inFrame->pCompletionProc, NULL);
}

リスト 4b DecompressSequenceFrameWhen を包む別のラッパー

非同期伸張

ICMCompletionProcRecord に RefCon と完了関数を指定することによって、伸張を非同期に実行できます。図 5a を参照してください。この場合、デコンプレッサが、codecCompletionDest フラグをセットした状態で完了関数を呼び出し、処理が完了したことを示すまで、伸張された画像を読み込まないようにする必要があります。リスト 5 を参照してください。

完了関数は何回か呼び出されることがあるため、割り込みセーフでなければなりません。asyncCompletionProc に NULL を渡すことは、同期圧縮であることを示します。

さらに、DecompressSequenceFrameWhen に、ICMFrameTimeRecord へのポインタを渡せば、定期伸張を行うこともできます。図 5b を参照してください。この構造体には、フレームが伸張される時間、所要時間、および再生速度を含む、フレームの時間情報を指定するパラメータが含まれています。定期伸張を実装する場合、上で説明した ICMCompletionProc も必ず実装してください。このパラメータには NULL も指定できます。その場合は、伸張処理が即座に実行されます。

// 画像圧縮完了コールバックを指定する
struct ICMCompletionProcRecord {
    ICMCompletionUPP completionProc;   // ICMCompletionProc に
                                       // アクセスする UPP
    long             completionRefCon; // このコールバックで使う refcon
};
typedef struct ICMCompletionProcRecord
                    ICMCompletionProcRecord;
typedef ICMCompletionProcRecord *
                    ICMCompletionProcRecordPtr;

// 非同期処理の完了時に、コンプレッサコンポーネント
// に呼び出される
typedef void (*ICMCompletionProcPtr) (OSErr result,
                                short flags, long refcon);
void MyICMCompletionProc(
    OSErr result   // 現在の処理の結果
    short flags    // どの処理が完了したか
                   // を示すフラグ
    long  refcon); // ICMCompletionProcRecord で
                   // 指定されたrefcon

図 5a ICMCompletionProcRecord および ICMCompletionProc


// 定期非同期伸張処理用の
// フレームの時間情報を含む
struct ICMFrameTimeRecord {
    wide     value;            // フレームが表示される時間
    long     scale;            // フレームの表示時間の単位
    void *   base;             // 時間のベース
    long     duration;         // フレーム表示の所要時間
                               // scale フィールドで指定された
                               // 単位と同じでなければならない
                               // 所要時間が不明の場合は 0 
    Fixed    rate;             // 時間のベースの実効速度
    long     recordSize;       // この構造体のサイズ
    long     frameNumber;      // フレーム番号が不明の場合は 0
    long     flags;            // フラグ
    wide     virtualStartTime; // 概念上の開始時間
    long     virtualDuration;  // 概念上の所要時間
};

図 5b ICMFrameTimeRecord


// ICM の伸張完了プロシージャのサンプル。
// このプロシージャでは、ICM が伸張先バッファを使い終わったかどうかを
// 示す codecCompletionDest フラグのステータスをチェックするだけ。
// FrameRecordPtr は、アプリケーションに関連付けられている、
// フレームごとに情報をトラッキングする何らかの型のデータ構造体
// とする。
// 注:関数は何回か呼び出されることがあるため、割り込みセーフで
// なければならない。
static pascal void DecompressionDone(OSErr inResult,
                                short inFlags, long inRefCon)
{
    FrameRecordPtr theFrame = (FrameRecordPtr)inRefCon;

    if (noErr == inResult) {
        if (codecCompletionDest & inFlags) {

            // ICM は出力先を使い終わった
            theFrame->isDestDone = true;

            ...
        }
    }

    theFrame->rc = inResult;
}

リスト 5 ICM の伸張完了プロシージャのサンプル

ピクセルへのアクセス

ピクセルに直接アクセスするには、GetGWorldPixMap を使って、伸張先の GWorld から PixMapHandle を取得して、ピクセル画像の先頭へのポインタを戻す GetPixBaseAddr を呼び出します。

GetPixRowBytes または QTGetPixMapHandleRowBytes を使って、ハンドルによってアクセスされるピクセルマップの rowBytes 値(画像データのある行の先頭から、次の行の先頭までの距離(バイト単位))を取得できるのに対し、QTGetPixMapPtrRowBytes は、同じことをポインタによってアクセスされるピクセルマップに対して行います。図 6 を参照してください。

オフスクリーンのピクセル画像のピクセルマップからのコピー中またはそこへの描画中に、ピクセル画像のベースアドレスが移動しないように、必ず LockPixels を呼び出すようにしてください。

// 次のような構造体を使って、32 ビットピクセル
// マップをピクセルの配列として簡単にキャストできる。
typedef struct {
      UInt8 alpha;  // アルファのコンポーネント
      UInt8 red;    // 赤のコンポーネント
      UInt8 green;  // 緑のコンポーネント
      UInt8 blue;   // 青のコンポーネント
} ARGBPixelRecord, *ARGBPixelPtr, **ARGBPixelHdl;

PixMapHandle hPixMap     = GetGWorldPixMap(myDestGWorld);
long         theRowBytes = QTGetPixMapHandleRowBytes(hPixMap);
Ptr          pPixels     = GetPixBaseAddr(hPixMap);

図 6 ピクセルへの直接のアクセス

シーケンスのセットアップ関数。リスト 6 を参照してください。

シーケンスの終了

シーケンス全体が伸張されたら、CDSequenceEnd を呼び出して、処理を終了します。このとき、一意の画像シーケンス ID を渡します。図 7 を参照してください。

シーケンスの終了関数。リスト 7 を参照してください。

OSErr CDSequenceEnd(ImageSequence seqID);

図 7 CDSequenceEnd API


// 伸張シーケンスをセットアップする方法の一例を示す
// サンプル関数。
// このサンプルの目的のために、冗長な値の割り当てを行う
// MyAppObjectPtr は、アプリケーションに関連付けられている、重要な
// ビットをすべてトラッキングする、何らかの型のデータ構造体を想定している。
OSErr SetupDecompressionSequenceForDV(MyAppObjectPtr inAppObject)
{
    ImageDescriptionHandle hImageDescription = NULL;
    GWorldPtr              theGWorld = NULL;
    ImageSequence          theSequenceID = 0;
    PixMapHandle           hPixMap = NULL;
    long                   theRowBytes = 0;
    Ptr                    pPixels = NULL;

    OSErr err = noErr;

    hImageDescription = MakeImageDescriptionForDV();
    err = MemError();

    if (hImageDescription) {
        // GWorld が、圧縮された画像とまったく同じサイズである
        // 必要はない
        err = MakeGWorld(&theGWorld,
                (*desc)->width, (*desc)->height);
        if (err) goto bail;

        err = MakeDecompressionSequence(hImageDescription,
                                theGWorld, &theSequenceID);
        if (err) goto bail;

        // ピクセルの BaseAddress および RowBytes を取得する
        hPixMap     = GetGWorldPixMap(theGWorld);
        pPixels     = GetPixBaseAddr(hPixMap);
        theRowBytes = QTGetPixMapHandleRowBytes(hPixMap);

        // これが必要としている情報
        inAppObject->dSeqID   = theSequenceID;
        inAppObject->pGWorld  = theGWorld;
        inAppObject->pPixels  = pPixels;
        inAppObject->rowBytes = theRowBytes;
    }

bail:
    if (hImageDescription)
        DisposeHandle((Handle)hImageDescription);

    return err;
}

リスト 6 伸張シーケンスのセットアップを示すサンプル関数


// 伸張シーケンスを終了する方法の一例を示すサンプル。
// MyAppObjectPtr は、アプリケーションに関連付けられ、重要な
// ビットをすべてトラッキングする何らかの型のデータ構造体とする。
OSErr EndDecompressionSequenceForDV(MyAppObjectPtr inAppObject)
{
    OSErr err = noErr;

    // 伸張シーケンスを終了する
    if (0 != inAppObject->dSeqID) {
        err = CDSequenceEnd(inAppObject->dSeqID);
        inAppObject->dSeqID = 0;
    }

    // GWorld を破棄する
    if (NULL != inAppObject->pGWorld)
        DisposeGWorld(inAppObject->pGWorld);

    inAppObject->pGWorld  = NULL;
    inAppObject->pPixels  = NULL;
    inAppObject->rowBytes = 0;

    return err;
}

リスト 7 伸張シーケンスの終了方法を示すサンプル関数

先頭に戻る

参考文献

QTNewGWorld

ImageDescription Structure

ImageDescription

Working with Image Descriptions

DecompressSequenceBeginS

DecompressSequenceFrameWhen

ICMCompletionProcRecord

ICMCompletionProc

ICMFrameTimeRecord

Working with Sequences

Image Compression Manager

Decompressing Sequences

Changing Sequence-Decompression Parameters

先頭に戻る

ダウンロード

Acrobat gif

このテクニカルノートの PDF 版

ダウンロード